package com.system.cacheCenterBackend.service;

import com.system.cacheCenterBackend.service.cacheService.CaffeineCacheServiceImpl;
import com.system.cacheCenterBackend.service.HotKeyService.HotKeyCounterService;
import com.system.cacheCenterBackend.service.cacheService.RedisCacheServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 二级缓存服务实现类
 * 先查询Caffeine，如果不存在则查询Redis
 * 实现热点缓存功能：当key访问次数达到阈值后才加入Caffeine缓存
 */
@Service
public class CacheServiceImpl implements CacheService {

    @Autowired
    private CaffeineCacheServiceImpl caffeineCacheService;

    @Autowired
    private RedisCacheServiceImpl redisCacheService;

    @Autowired
    private HotKeyCounterService hotKeyCounterService;

    @Override
    @Async("cacheExecutor")
    public boolean set(String key, String value) {
        // 同时设置两级缓存
        boolean caffeineResult = caffeineCacheService.set(key, value);
        boolean redisResult = redisCacheService.set(key, value);
        return caffeineResult && redisResult;
    }

    @Override
    @Async("cacheExecutor")
    public boolean set(String key, String value, long timeout) {
        // 同时设置两级缓存
        boolean caffeineResult = caffeineCacheService.set(key, value);
        boolean redisResult = redisCacheService.set(key, value, timeout);
        return caffeineResult && redisResult;
    }

    @Override
    public String get(String key) {
        // 异步增加key访问次数统计
        hotKeyCounterService.incrementKeyCountAsync(key);

        // 先从Caffeine中获取
        String value = caffeineCacheService.get(key);
        if (value != null) {
            return value;
        }

        // 如果Caffeine中没有，则从Redis中获取
        value = redisCacheService.get(key);
        if (value != null) {
            // 检查是否为热点key，如果是则放入Caffeine中，以便下次快速访问
            if (hotKeyCounterService.isHotKey(key)) {
                // 异步将热点数据放入Caffeine缓存
                setToCaffeineAsync(key, value);
            }
            return value;
        }

        // 两级缓存都没有
        return null;
    }

    @Async("cacheExecutor")
    public void setToCaffeineAsync(String key, String value) {
        caffeineCacheService.set(key, value);
    }

    @Override
    @Async("cacheExecutor")
    public boolean delete(String key) {
        // 同时删除两级缓存
        boolean caffeineResult = caffeineCacheService.delete(key);
        boolean redisResult = redisCacheService.delete(key);
        
        // 异步重置热点key统计
        hotKeyCounterService.resetKeyCountAsync(key);
        
        return caffeineResult && redisResult;
    }

    @Override
    public boolean exists(String key) {
        // 先检查Caffeine中是否存在
        if (caffeineCacheService.exists(key)) {
            return true;
        }
        // 如果Caffeine中不存在，则检查Redis中是否存在
        return redisCacheService.exists(key);
    }

    @Override
    public int getKeyAccessCount(String key) {
        return hotKeyCounterService.getKeyCount(key);
    }

    @Async("cacheExecutor")
    public CompletableFuture<Integer> getKeyAccessCountAsync(String key) {
        return hotKeyCounterService.getKeyCountAsync(key);
    }

    @Override
    public boolean isHotKey(String key) {
        return hotKeyCounterService.isHotKey(key);
    }

    @Override
    @Async("cacheExecutor")
    public void resetKeyStatistics(String key) {
        hotKeyCounterService.resetKeyCountAsync(key);
    }
    
    @Override
    public Map<String, String> getHash(String key) {
        // 异步增加key访问次数统计
        hotKeyCounterService.incrementKeyCountAsync(key);
        
        // 先从Caffeine中获取
        Map<String, String> value = caffeineCacheService.getHash(key);
        if (value != null) {
            return value;
        }
        
        // 如果Caffeine中没有，则从Redis中获取
        value = redisCacheService.getHash(key);
        if (value != null) {
            // 检查是否为热点key，如果是则放入Caffeine中，以便下次快速访问
            if (hotKeyCounterService.isHotKey(key)) {
                // 异步将热点数据放入Caffeine缓存
                setHashToCaffeineAsync(key, value);
            }
            return value;
        }
        
        // 两级缓存都没有
        return null;
    }
    
    @Async("cacheExecutor")
    public void setHashToCaffeineAsync(String key, Map<String, String> value) {
        caffeineCacheService.setHash(key, value);
    }
    
    @Override
    public List<String> getList(String key) {
        // 异步增加key访问次数统计
        hotKeyCounterService.incrementKeyCountAsync(key);
        
        // 先从Caffeine中获取
        List<String> value = caffeineCacheService.getList(key);
        if (value != null) {
            return value;
        }
        
        // 如果Caffeine中没有，则从Redis中获取
        value = redisCacheService.getList(key);
        if (value != null) {
            // 检查是否为热点key，如果是则放入Caffeine中，以便下次快速访问
            if (hotKeyCounterService.isHotKey(key)) {
                // 异步将热点数据放入Caffeine缓存
                setListToCaffeineAsync(key, value);
            }
            return value;
        }
        
        // 两级缓存都没有
        return null;
    }
    
    @Async("cacheExecutor")
    public void setListToCaffeineAsync(String key, List<String> value) {
        caffeineCacheService.setList(key, value);
    }
    
    @Override
    public Set<String> getSet(String key) {
        // 异步增加key访问次数统计
        hotKeyCounterService.incrementKeyCountAsync(key);
        
        // 先从Caffeine中获取
        Set<String> value = caffeineCacheService.getSet(key);
        if (value != null) {
            return value;
        }
        
        // 如果Caffeine中没有，则从Redis中获取
        value = redisCacheService.getSet(key);
        if (value != null) {
            // 检查是否为热点key，如果是则放入Caffeine中，以便下次快速访问
            if (hotKeyCounterService.isHotKey(key)) {
                // 异步将热点数据放入Caffeine缓存
                setSetToCaffeineAsync(key, value);
            }
            return value;
        }
        
        // 两级缓存都没有
        return null;
    }
    
    @Async("cacheExecutor")
    public void setSetToCaffeineAsync(String key, Set<String> value) {
        caffeineCacheService.setSet(key, value);
    }
    
    @Override
    public Set<String> getZSet(String key) {
        // 异步增加key访问次数统计
        hotKeyCounterService.incrementKeyCountAsync(key);
        
        // 先从Caffeine中获取
        Set<String> value = caffeineCacheService.getZSet(key);
        if (value != null) {
            return value;
        }
        
        // 如果Caffeine中没有，则从Redis中获取
        value = redisCacheService.getZSet(key);
        if (value != null) {
            // 检查是否为热点key，如果是则放入Caffeine中，以便下次快速访问
            if (hotKeyCounterService.isHotKey(key)) {
                // 异步将热点数据放入Caffeine缓存
                setZSetToCaffeineAsync(key, value);
            }
            return value;
        }
        
        // 两级缓存都没有
        return null;
    }
    
    @Async("cacheExecutor")
    public void setZSetToCaffeineAsync(String key, Set<String> value) {
        caffeineCacheService.setZSet(key, value);
    }
    
    @Override
    public Set<String> getAllStringKeys() {
        // 获取Redis中所有String类型的键
        // 这里简化实现，实际项目中需要根据具体的键命名规范来获取
        return Collections.emptySet();
    }
    
    @Override
    public Set<String> getAllHashKeys() {
        // 获取Redis中所有Hash类型的键
        // 这里简化实现，实际项目中需要根据具体的键命名规范来获取
        return Collections.emptySet();
    }
    
    @Override
    public Set<String> getAllListKeys() {
        // 获取Redis中所有List类型的键
        // 这里简化实现，实际项目中需要根据具体的键命名规范来获取
        return Collections.emptySet();
    }
    
    @Override
    public Set<String> getAllSetKeys() {
        // 获取Redis中所有Set类型的键
        // 这里简化实现，实际项目中需要根据具体的键命名规范来获取
        return Collections.emptySet();
    }
    
    @Override
    public Set<String> getAllZSetKeys() {
        // 获取Redis中所有ZSet类型的键
        // 这里简化实现，实际项目中需要根据具体的键命名规范来获取
        return Collections.emptySet();
    }
}